package com.sam.redis.pool;

import java.util.HashMap;
import java.util.Map;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

public class JedisPoolUtil {

    /** 构造器私有 **/
    private JedisPoolUtil() {

    }

    private static final Map<String, JedisPool> maps = new HashMap<String, JedisPool>();

    /**
     * @功能说明:创建redis连接池对象.
     * @param RedisConfig
     *            配置对象
     * @return JedisPool
     * @返回类型:JedisPool
     * @方法名称:getPool
     * @类名称:JedisPoolUtil
     * @文件名称:JedisPoolUtil.java
     * @所属包名:com.sam.redis.pool
     * @项目名称:redis
     * @创建时间:2017-8-3 下午1:51:34
     * @作者:SAM QZL
     * @版本:1.0
     */
    private static JedisPool getPool(RedisConfig configs) {

        /** 访问地址 **/
        String uri = configs.ip + ":" + configs.port;
        JedisPool pool = null;
        if (!maps.containsKey(uri)) {
            JedisPoolConfig config = new JedisPoolConfig();
            config.setMaxTotal(configs.maxTotal);
            config.setMaxIdle(configs.maxidle);
            config.setMinIdle(configs.mindle);
            config.setMaxWaitMillis(configs.maxWaitMillis);
            config.setTestOnBorrow(configs.testOnBorrow);
            config.setTestOnReturn(configs.testOnReturn);
            config.setTestWhileIdle(configs.testWhileIdle);
            /** 创建连接数对象 **/
            pool = new JedisPool(config, configs.ip, configs.port, configs.timeout, configs.passowrd);
            /** 加入map **/
            maps.put(uri, pool);
        }
        else {
            pool = maps.get(uri);
        }
        return pool;
    }

    /**
     * @功能说明:获取redis连接对象.
     * @param configs
     * @return Jedis
     * @返回类型:Jedis
     * @方法名称:getJedis
     * @类名称:JedisPoolUtil
     * @文件名称:JedisPoolUtil.java
     * @所属包名:com.sam.redis.pool
     * @项目名称:redis
     * @创建时间:2017-8-3 下午2:11:53
     * @作者:SAM QZL
     * @版本:1.0
     */
    public Jedis getJedis(RedisConfig configs) {

        Jedis jedis = getPool(configs).getResource();
        return jedis;
    }

    /**
     * @功能说明:释放实例到连接池.
     * @param jedis
     * @param configs
     * @返回类型:void
     * @方法名称:closeJedis
     * @类名称:JedisPoolUtil
     * @文件名称:JedisPoolUtil.java
     * @所属包名:com.sam.redis.pool
     * @项目名称:redis
     * @创建时间:2017-8-3 下午2:12:53
     * @作者:SAM QZL
     * @版本:1.0
     */
    public void closeJedis(Jedis jedis) {

        if (jedis != null) {
            jedis.close();
        }
    }

    /**
     * 
     * <b>项目名称</b>：redis<br>
     * <b>类名称</b>：RedisUtilHolder<br>
     * <b>类描述</b>：单例实现<br>
     * <b>创建人</b>：SAM QZL<br>
     * <b>创建时间</b>：2017-8-3 下午1:55:25<br>
     * <b>修改人</b>：SAM QZL<br>
     * <b>修改时间</b>：2017-8-3 下午1:55:25<br>
     * <b>修改备注</b>：<br>
     * @author SAM QZL<br>
     * @version
     * 
     */
    private static class RedisUtilHolder {

        /**
         * 静态初始化器，由JVM来保证线程安全
         */
        private static final JedisPoolUtil instance = new JedisPoolUtil();
    }

    /**
     * @功能说明:获取redis连接池工具类【单例】.
     * @return JedisPoolUtil
     * @返回类型:JedisPoolUtil
     * @方法名称:getInstance
     * @类名称:JedisPoolUtil
     * @文件名称:JedisPoolUtil.java
     * @所属包名:com.sam.redis.pool
     * @项目名称:redis
     * @创建时间:2017-8-3 下午1:56:52
     * @作者:SAM QZL
     * @版本:1.0
     */
    public static JedisPoolUtil getInstance() {

        return RedisUtilHolder.instance;
    }

    /**
     * <b>项目名称</b>：redis<br>
     * <b>类名称</b>：RedisConfig<br>
     * <b>类描述</b>：配置类<br>
     * <b>创建人</b>：SAM QZL<br>
     * <b>创建时间</b>：2017-8-3 下午2:08:21<br>
     * <b>修改人</b>：SAM QZL<br>
     * <b>修改时间</b>：2017-8-3 下午2:08:21<br>
     * <b>修改备注</b>：<br>
     * @author SAM QZL<br>
     * @version
     * 
     */
    public static class RedisConfig {

        /** 默认配置实例 **/
        public static final RedisConfig REDIS_CONFIG_DEFAULT = new RedisConfig(1000, 100, 100, 20000, true, true, true, 10000, "Qzl12345689", "39.108.152.183", 6379);
        /** 最大实例数 **/
        private final Integer maxTotal;
        /** 最大空闲实例数 **/
        private final Integer maxidle;
        /** 最小空闲实例数 **/
        private final Integer mindle;
        /** 表示当(引入)一个jedis实例时，最大的等待时间，如果超过等待时间，则直接抛出JedisConnectionException **/
        private final Integer maxWaitMillis;
        /** 在borrow一个jedis实例时，是否提前进行alidate操作；如果为true，则得到的jedis实例均是可用的 **/
        private final boolean testOnBorrow;
        /** 返回实例是否校验 **/
        private final boolean testOnReturn;
        /** 实例空闲时是否校验 **/
        private final boolean testWhileIdle;
        /** 超时 **/
        private final Integer timeout;
        /** 密码 **/
        private final String passowrd;
        /** 主机IP **/
        private final String ip;
        /** 端口 **/
        private final Integer port;

        public RedisConfig(Integer maxTotal, Integer maxidle, Integer mindle,
                Integer maxWaitMillis, boolean testOnBorrow, boolean testOnReturn,
                boolean testWhileIdle, Integer timeout, String passowrd, String ip, Integer port) {

            this.maxTotal = maxTotal;
            this.maxidle = maxidle;
            this.mindle = mindle;
            this.maxWaitMillis = maxWaitMillis;
            this.testOnBorrow = testOnBorrow;
            this.testOnReturn = testOnReturn;
            this.testWhileIdle = testWhileIdle;
            this.timeout = timeout;
            this.passowrd = passowrd;
            this.ip = ip;
            this.port = port;
        }

        /**
         * passowrd
         * 
         * @return the passowrd
         * @since CodingExample Ver(编码范例查看) 1.0
         */
        public String getPassowrd() {

            return passowrd;
        }

        /**
         * ip
         * 
         * @return the ip
         * @since CodingExample Ver(编码范例查看) 1.0
         */
        public String getIp() {

            return ip;
        }

        /**
         * port
         * 
         * @return the port
         * @since CodingExample Ver(编码范例查看) 1.0
         */
        public Integer getPort() {

            return port;
        }

        /**
         * maxTotal
         * 
         * @return the maxTotal
         * @since CodingExample Ver(编码范例查看) 1.0
         */
        public Integer getMaxTotal() {

            return maxTotal;
        }

        /**
         * maxidle
         * 
         * @return the maxidle
         * @since CodingExample Ver(编码范例查看) 1.0
         */
        public Integer getMaxidle() {

            return maxidle;
        }

        /**
         * mindle
         * 
         * @return the mindle
         * @since CodingExample Ver(编码范例查看) 1.0
         */
        public Integer getMindle() {

            return mindle;
        }

        /**
         * maxWaitMillis
         * 
         * @return the maxWaitMillis
         * @since CodingExample Ver(编码范例查看) 1.0
         */
        public Integer getMaxWaitMillis() {

            return maxWaitMillis;
        }

        /**
         * testOnBorrow
         * 
         * @return the testOnBorrow
         * @since CodingExample Ver(编码范例查看) 1.0
         */
        public boolean isTestOnBorrow() {

            return testOnBorrow;
        }

        /**
         * testOnReturn
         * 
         * @return the testOnReturn
         * @since CodingExample Ver(编码范例查看) 1.0
         */
        public boolean isTestOnReturn() {

            return testOnReturn;
        }

        /**
         * testWhileIdle
         * 
         * @return the testWhileIdle
         * @since CodingExample Ver(编码范例查看) 1.0
         */
        public boolean isTestWhileIdle() {

            return testWhileIdle;
        }

        /**
         * timeout
         * 
         * @return the timeout
         * @since CodingExample Ver(编码范例查看) 1.0
         */
        public Integer getTimeout() {

            return timeout;
        }
    }
}
